home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / xref_v1.1.lha / XRef / Tools / source / makexref.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-09  |  33.8 KB  |  1,203 lines

  1. ;/* execute me to make with SAS 6.x
  2. sc NOSTKCHK CSRC makexref.c OPT IGNORE=73
  3. slink lib:c.o makexref.o //Goodies/extrdargs/extrdargs.o TO /c/makexref SMALLDATA SMALLCODE NOICONS LIB lib:amiga.lib lib:sc.lib /lib/xrefsupport.lib
  4. quit
  5. */
  6.  
  7. /*
  8. ** $PROJECT: XRef-Tools
  9. **
  10. ** $VER: makexref.c 1.20 (19.11.94)
  11. **
  12. ** by
  13. **
  14. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  15. **
  16. ** (C) Copyright 1994
  17. ** All Rights Reserved !
  18. **
  19. ** $HISTORY:
  20. **
  21. ** 19.11.94 : 001.020 :  new AUTHOR,NAME options, generates now VERSTAG
  22. ** 03.11.94 : 001.019 :  default icon name now env:sys/def_xref
  23. ** 25.09.94 : 001.018 :  line var in scan_header() now correct
  24. ** 24.09.94 : 001.017 :  if only a file is given, this wasn't opened. This is fixed
  25. ** 10.09.94 : 001.016 :  now uses a status window, if started from workbench
  26. ** 07.09.94 : 001.015 :  workbench support added (FinalReadArgs())
  27. ** 03.09.94 : 001.014 :  now uses ENTRYA_NodeName
  28. ** 29.08.94 : 001.013 :  unix manpages support added
  29. ** 28.07.94 : 001.012 :  only shift-space in scan_amigaguide was searched, this is now fixed
  30. ** 20.07.94 : 001.011 :  PATH option added
  31. ** 09.07.94 : 001.010 :  added support for typedefs etc, some bug fixes
  32. ** 19.06.94 : 001.009 :  changed to new library entry functions
  33. ** 05.06.94 : 001.008 :  strip '.doc' for an autodoc file and append ".guide" for an doc
  34. ** 22.05.94 : 001.007 :  ctrl-c support added
  35. ** 22.05.94 : 001.006 :  modularized and globaldata added
  36. ** 10.05.94 : 001.005 :  length byte after the type byte added
  37. ** 07.05.94 : 001.004 :  path for a file argument corrected
  38. ** 27.04.94 : 001.003 :  filepath corrected
  39. ** 26.04.94 : 001.002 :  verbose arg added and version change to 1
  40. ** 15.01.94 : 000.001 :  initial
  41. **
  42. */
  43.  
  44. #include "Def.h"
  45.  
  46. #include <libraries/xref.h>
  47. #include <clib/xref_protos.h>
  48. #include <pragmas/xref_pragmas.h>
  49.  
  50. #include "/lib/xrefsupport.h"
  51.  
  52. #include "makexref_rev.h"
  53.  
  54. /* ------------------------------- AutoDoc -------------------------------- */
  55.  
  56. /*FS*/ /*"AutoDoc"*/
  57. /*GB*** XRef-Tools/MakeXRef **************************************************
  58.  
  59. $VER: MakeXRef.doc
  60.  
  61. NAME
  62.     MakeXRef - generate a xreffile for amigaguide from c-header, amigaguide,
  63.                autodoc, unix man pages and normal doc files
  64.  
  65. TEMPLATE
  66.     FROM/A/M,TO/A,CATEGORY/K,PATH/K,VERSION/N/K,REVISION/N/K,VERBOSE
  67.  
  68. FORMAT
  69.     MakeXRef [FROM] file|dir [file2|dir2] [TO] file [CATEGORY category] 
  70.              [PATH gpath] [VERSION versionnr] [REVISION revisionnr] [VERBOSE]
  71.  
  72. FUNCTION
  73.     generate xref-file for use with xref.library.This tool scans any autodoc,
  74.     amigaguide ,C-Header, unix man page and normal doc file. The following 
  75.     entry types are recognized :
  76.         in C-Header files :
  77.         - normal define's
  78.         - macro define's
  79.         - structures
  80.         - typedef's
  81.         in autodoc,amigaguide, unix man page and normal doc files :
  82.         - function's
  83.         - command's (device command's for example)
  84.         - generic (all other entries, which doesn't fit in the types above)
  85.  
  86.     If started from workbench, it opens a status window, which displays the
  87.     current state of the program. Also it calculates the time to be used until
  88.     the program finishes. Take just a look at !
  89.  
  90. INPUTS
  91.     FROM    - File(s) or director(y|ies) to scan
  92.  
  93.     TO      - File to hold all xref-entries
  94.  
  95.     CATEGORY- category to use implicit for this xreffile (this is saved in
  96.               the xreffile). Note this is the specification of the category,
  97.               so you can't use any pattern !
  98.  
  99.     PATH    - global path, which is prepend to each filename for a entry, so
  100.               you can build absolute filepath for a entry, this path is stored
  101.               only once in a xreffile.
  102.  
  103.     VERSION - version of the created xreffile
  104.  
  105.     REVISION- revision of the created xreffile
  106.  
  107.     NOICON  - don't create a icon for the generated xreffile
  108.  
  109.     VERBOSE - switch, that indicate you want to see the found entries
  110.  
  111. SEE ALSO
  112.     ParseXRef, AGuideXRefV37, AGuideXRefV39, LoadXRef, ExpungeXRef,
  113.     libraries/amigaguide.h, libraries/xref.h
  114.  
  115. COPYRIGHT
  116.     (C) by Stefan Ruppert 1994
  117.  
  118. HISTORY
  119.     MakeXRef 1.20 (19.11.94) :
  120.         - new AUTHOR,NAME options
  121.         - generates now AmigaDOS 2.0 version string
  122.  
  123.     MakeXRef 1.19 (3.11.94) :
  124.         - intern Icon definition corrected
  125.  
  126.     MakeXRef 1.18 (25.9.94) :
  127.         - in header files line number was not correct in some cases
  128.  
  129.     MakeXRef 1.17 (24.9.94) :
  130.         - if only a file was passed , it wasn't opened . This is fixed !
  131.  
  132.     MakeXRef 1.16 (10.9.94) :
  133.         - status window added , if started from Workbench
  134.  
  135.     MakeXRef 1.15 (7.9.94) :
  136.         - workbench support added
  137.         - now patterns can be used for the FROM argument
  138.  
  139.     MakeXRef 1.14 (3.9.94) :
  140.         - some changes to reflect new tags
  141.         - scan_man() function now strips backspaces
  142.  
  143.     MakeXRef 1.13 (29.8.94) :
  144.         - added support of unix manual pages
  145.  
  146.     MakeXRef 1.12 (28.7.94) :
  147.         - in amigaguide scan , there was a bug, which interpreted a space in a
  148.           a node name as a normal character. This is fixed !
  149.         - path now check for last character (':','/')
  150.  
  151.     MakeXRef 1.11 (20.7.94) :
  152.         - PATH option added.
  153.  
  154.     MakeXRef 1.10 (9.7.94) :
  155.         - added support for typedefs, macros, commands and generic
  156.         - now handles datatypes,gadgets and handlers as generic
  157.         - some bug fixes
  158.  
  159.     MakeXRef 1.9 (19.6.94) :
  160.         - now uses the xref.library function to create a xreffile
  161.           the library handles now all entry and file names.It sorts
  162.           all names and create an index for each entry.
  163.  
  164.     MakeXRef 1.8 (5.6.94) :
  165.         - now strips ".doc" from an autodoc file in the xref file
  166.  
  167.     MakeXRef 1.7 (22.5.94) :
  168.         - now supports C-header files
  169.  
  170.     MakeXRef 1.6 (10.5.94) :
  171.         - xref file format changed
  172.  
  173.     MakeXRef 1.5 (7.5.94) :
  174.         - first beta release
  175.  
  176. *****************************************************************************/
  177. /*FE*/
  178.  
  179. /* ------------------------------ Prototypes ------------------------------ */
  180.  
  181. /*FS*/ /*"Prototypes"*/
  182.  
  183. RegCall LONG scan_file(REGA0 struct Hook *hook,REGA2 struct GlobalData *gd,REGA1 struct spMsg *msg);
  184.  
  185. void scan_header(struct GlobalData *gd);
  186. void scan_autodoc(struct GlobalData *gd);
  187. void scan_amigaguide(struct GlobalData *gd);
  188. void scan_man(struct GlobalData *gd);
  189.  
  190. BOOL check_abort(struct GlobalData *gd);
  191.  
  192. void draw_info(struct GlobalData *gd,STRPTR entry,ULONG entrytype);
  193. void draw_state(struct GlobalData *gd);
  194.  
  195. /*FE*/
  196.  
  197. /* ----------------------------- definitions ------------------------------ */
  198.  
  199. /*FS*/ /*"Defines"*/
  200. #define BUFFER_LEN   1024
  201. #define PATH_LEN     512
  202.  
  203. #define EOS          '\0'
  204.  
  205. #define LINE_UPDATE    50
  206.  
  207. /*FE*/
  208.  
  209. /* ------------------------------ Structures ------------------------------ */
  210.  
  211. /*FS*/ /*"Structure definition"*/
  212. struct GlobalData
  213. {
  214.    ULONG *gd_Para;
  215.  
  216.    BPTR gd_ReadFH;
  217.    APTR gd_XRefFile;
  218.  
  219.    BOOL gd_Workbench;                  /* TRUE -> started from workbench */
  220.    BOOL gd_Abort;
  221.  
  222.    ULONG gd_FileType;                  /* actual filetype of the current file */
  223.    ULONG gd_FileSize;                  /* actual filesize of the current file */
  224.    ULONG gd_Line;
  225.  
  226.    struct ScanWindow gd_SWin;
  227.    struct ScanStat gd_SStat;
  228.    struct TimeCalc gd_TimeCalc;
  229.  
  230.    ULONG gd_Entries;
  231.  
  232.    STRPTR gd_FileName;
  233.    UBYTE gd_TempPath[PATH_LEN];
  234.  
  235.    UBYTE gd_LineBuffer[BUFFER_LEN];
  236.    UBYTE gd_TempBuffer[BUFFER_LEN];
  237.  
  238.    struct Library *gd_XRefBase;
  239. };
  240.  
  241. #define XRefBase     gd->gd_XRefBase
  242. /*FE*/
  243.  
  244. /* ------------------------------ Icon data ------------------------------- */
  245.  
  246. /*FS*/ /*"Icon Data"*/
  247. /****** Image def_xref.info : w = 64, h = 22 ********/
  248. UWORD def_xref_infoIData[176] = {
  249. /*------ plane # 0: --------*/
  250.         0x0000, 0x0000, 0x0000, 0x0400, 
  251.         0x0000, 0x0000, 0x0000, 0x0C00, 
  252.         0x0000, 0x0000, 0x0000, 0x0C00, 
  253.         0x0030, 0x0060, 0x0000, 0x0C00, 
  254.         0x0018, 0x00C0, 0x0000, 0x0C00, 
  255.         0x000C, 0x0180, 0x0000, 0x0C00, 
  256.         0x0006, 0x0300, 0x0010, 0x0C00, 
  257.         0x0003, 0x0600, 0x0018, 0x0C00, 
  258.         0x0001, 0x8C00, 0x001C, 0x0C00, 
  259.         0x0000, 0xD800, 0x001E, 0x0C00, 
  260.         0x0000, 0x7007, 0xFFFF, 0x0C00, 
  261.         0x0000, 0x7007, 0xFFFF, 0x0C00, 
  262.         0x0000, 0xD800, 0x001E, 0x0C00, 
  263.         0x0001, 0x8C00, 0x001C, 0x0C00, 
  264.         0x0003, 0x0600, 0x0018, 0x0C00, 
  265.         0x0006, 0x0300, 0x0010, 0x0C00, 
  266.         0x000C, 0x0180, 0x0000, 0x0C00, 
  267.         0x0018, 0x00C0, 0x0000, 0x0C00, 
  268.         0x0030, 0x0060, 0x0000, 0x0C00, 
  269.         0x0000, 0x0000, 0x0000, 0x0C00, 
  270.         0x0000, 0x0000, 0x0000, 0x0C00, 
  271.         0x7FFF, 0xFFFF, 0xFFFF, 0xFC00, 
  272. /*------ plane # 1: --------*/
  273.         0xFFFF, 0xFFFF, 0xFFFF, 0xF800, 
  274.         0xEAAA, 0xAAAA, 0xAAAA, 0xA000, 
  275.         0xEAFA, 0xAAFA, 0xAAAA, 0xA000, 
  276.         0xEAC2, 0xAB8A, 0xAAAA, 0xA000, 
  277.         0xEAE2, 0xAB0A, 0xAAAA, 0xA000, 
  278.         0xEAB0, 0xAE0A, 0xAAAA, 0xA000, 
  279.         0xEAB8, 0xAC2A, 0xAAA2, 0xA000, 
  280.         0xEAAC, 0x382A, 0xAAA2, 0xA000, 
  281.         0xEAAE, 0x30AA, 0xAAA0, 0xA000, 
  282.         0xEAAB, 0x00AF, 0xFFE0, 0xA000, 
  283.         0xEAAB, 0x82A8, 0x0000, 0x2000, 
  284.         0xEAAB, 0x82A8, 0x0000, 0x2000, 
  285.         0xEAAB, 0x02A8, 0x0000, 0x2000, 
  286.         0xEAAE, 0x10AA, 0xAAA0, 0xA000, 
  287.         0xEAAC, 0x38AA, 0xAAA0, 0xA000, 
  288.         0xEAB8, 0x2C2A, 0xAAA2, 0xA000, 
  289.         0xEAB0, 0xAE2A, 0xAAAA, 0xA000, 
  290.         0xEAE0, 0xAB0A, 0xAAAA, 0xA000, 
  291.         0xEAC2, 0xAB8A, 0xAAAA, 0xA000, 
  292.         0xEAE2, 0xAAEA, 0xAAAA, 0xA000, 
  293.         0xEAAA, 0xAAAA, 0xAAAA, 0xA000, 
  294.         0x8000, 0x0000, 0x0000, 0x0000, 
  295. };
  296.  
  297. struct Image def_xref_infoImg =
  298. {
  299.         0, 0,                    /* LeftEdge, TopEdge */
  300.         54, 22, 2,               /* Width, Height, Depth */
  301.         &def_xref_infoIData[0],  /* ImageData */
  302.         0x03, 0x00,              /* PlanePick, PlaneOnOff */
  303.         0L                       /* NextImage */
  304. };
  305.  
  306. STRPTR def_xref_tooltypes[] = {
  307.    "(XREFPRI=<priority>)",
  308.    "(LOCK)",
  309.    "(INDEX)",
  310.    NULL};
  311.  
  312. struct SaveDefIcon def_xref = {
  313.    "Env:Sys/def_xref",
  314.    "LoadXRef",
  315.    &def_xref_tooltypes[0],
  316.    &def_xref_infoImg};
  317.  
  318.  
  319. /*FE*/
  320.  
  321. /* ------------------------------- Template ------------------------------- */
  322.  
  323. /*FS*/ /*"Template definition"*/
  324. #define template "FROM/A/M,TO/A,CATEGORY/K,PATH/K,VERSION/N/K,REVISION/N/K," \
  325.                  "AUTHOR/K,NAME/K,NOICON/S,VERBOSE/S"
  326.  
  327. enum {
  328.    ARG_FROM,
  329.    ARG_TO,
  330.    ARG_CATEGORY,
  331.    ARG_PATH,
  332.    ARG_VERSION,
  333.    ARG_REVISION,
  334.    ARG_AUTHOR,
  335.    ARG_NAME,
  336.    ARG_NOICON,
  337.    ARG_VERBOSE,
  338.    ARG_MAX};
  339.  
  340. char *prgname    = "MakeXRef";
  341.  
  342. const char *version    = VERSTAG;
  343. const char *mainstring = "main";
  344.  
  345. char *displaytexts[] = {
  346.    "XReffile",
  347.    "Entries",
  348.    "Files",
  349.    "Dirs",
  350.    "Dir",
  351.    "File",
  352.    "Filetype",
  353.    "Entry",
  354.    NULL};
  355.  
  356. enum {
  357.    NUM_XREFFILE,
  358.    NUM_ENTRIES,
  359.    NUM_FILES,
  360.    NUM_DIRS,
  361.    NUM_DIR,
  362.    NUM_FILE,
  363.    NUM_FILETYPE,
  364.    NUM_ENTRY,
  365.    NUM_MAX};
  366.  
  367. const STRPTR etype[] = {
  368.    "generic",
  369.    "function",
  370.    "command",
  371.    "include",
  372.    "macro",
  373.    "struct",
  374.    "field",
  375.    "typedef",
  376.    "define",
  377.    NULL};
  378.  
  379. /*FE*/
  380.  
  381. /* --------------------------- main entry point --------------------------- */
  382.  
  383. /*FS*/ /*"int main(int ac,char *av[]) "*/
  384. int main(int ac,char *av[])
  385. {
  386.    struct ExtRDArgs eargs = {NULL};
  387.  
  388.    struct GlobalData *gd;
  389.  
  390.    ULONG para[ARG_MAX];
  391.  
  392.    STRPTR obj  = prgname;
  393.    LONG retval = RETURN_OK;
  394.    LONG err;
  395.  
  396.    WORD i;
  397.  
  398.    for( i = 0 ; i < ARG_MAX ; i++ )
  399.       para[i] = 0;
  400.  
  401.    eargs.erda_Template      = template;
  402.    eargs.erda_Parameter     = para;
  403.    eargs.erda_FileParameter = ARG_FROM;
  404.  
  405.    if((err = ExtReadArgs(ac,av,&eargs)) == 0)
  406.    {
  407.       para[ARG_VERSION]  = (para[ARG_VERSION])  ? *((ULONG *) para[ARG_VERSION])  : 1;
  408.       para[ARG_REVISION] = (para[ARG_REVISION]) ? *((ULONG *) para[ARG_REVISION]) : 1;
  409.  
  410.       if(gd = AllocVec(sizeof(struct GlobalData),MEMF_ANY | MEMF_CLEAR))
  411.       {
  412.          struct DateTime dt;
  413.          STRPTR verstag = NULL;
  414.          UBYTE dbuf[20];
  415.          UBYTE vtbuf[100];
  416.  
  417.          DateStamp(&dt.dat_Stamp);
  418.  
  419.          dt.dat_Format = FORMAT_CDN;
  420.          dt.dat_Flags  = 0;
  421.          dt.dat_StrDate= dbuf;
  422.          dt.dat_StrTime= NULL;
  423.          dt.dat_StrDay = NULL;
  424.  
  425.          if(DateToStr(&dt))
  426.          {
  427.             STRPTR ptr = dbuf;
  428.  
  429.             if(*ptr == '0')
  430.                while(*ptr = *(ptr + 1))
  431.                   ptr++;
  432.  
  433.             ptr = dbuf;
  434.             while(*ptr != '-')
  435.                ptr++;
  436.  
  437.             *ptr++ = '.';
  438.             if(*ptr == '0')
  439.                while(*ptr = *(ptr + 1))
  440.                   ptr++;
  441.  
  442.             ptr = dbuf;
  443.             while(*ptr != '-')
  444.                ptr++;
  445.             *ptr = '.';
  446.  
  447.             sprintf(vtbuf,"%lc$VER: %s %ld.%ld (%s)",'\0',
  448.                           FilePart((STRPTR) para[ARG_TO]),
  449.                           para[ARG_VERSION],
  450.                           para[ARG_REVISION],
  451.                           dbuf);
  452.             verstag = vtbuf;
  453.          }
  454.  
  455.          gd->gd_Workbench = (ac == 0);
  456.  
  457.          if(para[ARG_PATH])
  458.          {
  459.             ULONG len;
  460.             strcpy(gd->gd_TempPath,(STRPTR) para[ARG_PATH]);
  461.             len = strlen(gd->gd_TempPath)-1;
  462.             if(gd->gd_TempPath[len] != ':' && gd->gd_TempPath[len] != '/')
  463.                strcat(gd->gd_TempPath,"/");
  464.             para[ARG_PATH] = (ULONG) gd->gd_TempPath;
  465.          }
  466.  
  467.          obj = "xref.library";
  468.          if((XRefBase = OpenLibrary(obj,1)))
  469.          {
  470.             obj = (STRPTR) para[ARG_TO];
  471.             if(gd->gd_XRefFile = CreateXRefFile(obj,XREFA_Category ,para[ARG_CATEGORY],
  472.                                                     XREFA_VersTag  ,verstag,
  473.                                                     XREFA_Author   ,para[ARG_AUTHOR],
  474.                                                     XREFA_Name     ,para[ARG_NAME],
  475.                                                     XREFA_Path     ,para[ARG_PATH],
  476.                                                     TAG_DONE))
  477.             {
  478.                struct Hook scanfile_hook = {NULL};
  479.  
  480.                gd->gd_Para = para;
  481.                scanfile_hook.h_Entry = (HOOKFUNC) scan_file;
  482.  
  483.                if(ac == 0)
  484.                {
  485.                   open_scanwindow(&gd->gd_SWin,displaytexts,prgname,400);
  486.                   draw_scanwindowstatus(&gd->gd_SWin,"reading filelist ...");
  487.                }
  488.  
  489.                getscanstat((STRPTR *) para[ARG_FROM],&gd->gd_SStat);
  490.  
  491.                if(ac == 0)
  492.                {
  493.                   draw_scanwindowtext(&gd->gd_SWin,NUM_XREFFILE,(STRPTR) para[ARG_TO]);
  494.                   draw_scanwindowstatus(&gd->gd_SWin,"scanning ...");
  495.                }
  496.                
  497.                /* init time service structure */
  498.                time_init(&gd->gd_TimeCalc,LINE_UPDATE);
  499.  
  500.                err = scan_patterns((STRPTR *) para[ARG_FROM],&scanfile_hook,gd);
  501.  
  502.                CloseXRefFile(gd->gd_XRefFile);
  503.  
  504.                gd->gd_Abort |= (err == ERROR_BREAK);
  505.  
  506.                time_calc(&gd->gd_TimeCalc,1,1);
  507.  
  508.                if(gd->gd_Abort)
  509.                {
  510.                   DeleteFile((STRPTR) para[ARG_TO]);
  511.                   err = ERROR_BREAK;
  512.                   obj = prgname;
  513.                   Printf ("\r%s removed ! %-60s\n",(STRPTR) para[ARG_TO],"");
  514.                } else
  515.                {
  516.                   Printf ("\rFiles scanned : %ld, Entries found : %ld , Time used : %02ld:%02ld%-20s\n",
  517.                           gd->gd_SStat.ss_Files,gd->gd_Entries,
  518.                           gd->gd_TimeCalc.tc_Secs[TIME_USED] / 60,
  519.                           gd->gd_TimeCalc.tc_Secs[TIME_USED] % 60,
  520.                           "");
  521.  
  522.                   DB(("IoErr() = %ld\n",IoErr()));
  523.  
  524.                   if(!para[ARG_NOICON])
  525.                   {
  526.                      STRPTR xrefdir;
  527.                      BPTR dir = NULL;
  528.                      BPTR old;
  529.  
  530.                      if((FilePart((STRPTR) para[ARG_TO]) == ((STRPTR) para[ARG_TO])) &&
  531.                         (GetXRefBaseAttrs(XREFBA_XRefDir,&xrefdir,TAG_DONE) == 1))
  532.                      {
  533.                         if((dir = Lock(xrefdir,SHARED_LOCK)))
  534.                            old = CurrentDir(dir);
  535.                      }
  536.  
  537.                      saveicon((STRPTR) para[ARG_TO],&def_xref);
  538.  
  539.                      if(dir)
  540.                      {
  541.                         CurrentDir(old);
  542.                         UnLock(dir);
  543.                      }
  544.                   }
  545.  
  546.                   DB(("IoErr() = %ld\n",IoErr()));
  547.                }
  548.  
  549.                /* close all workbench stuff */
  550.                close_scanwindow(&gd->gd_SWin,gd->gd_Abort);
  551.             }
  552.  
  553.             CloseLibrary(XRefBase);
  554.          }
  555.          FreeVec(gd);
  556.       }
  557.    }
  558.    ExtFreeArgs(&eargs);
  559.  
  560.    if(!err)
  561.       err = IoErr();
  562.  
  563.    if(err)
  564.    {
  565.       if(ac == 0)
  566.          showerror(prgname,obj,err);
  567.       else
  568.          PrintFault(err,obj);
  569.  
  570.       retval = RETURN_ERROR;
  571.    }
  572.  
  573.    return(retval);
  574. }
  575. /*FE*/
  576.  
  577. /* ------------------------------ scan_file ------------------------------- */
  578.  
  579. /*FS*/ /*"LONG scan_file(struct Hook *hook,struct GlobalData *gd,struct spMsg *msg)"*/
  580. RegCall LONG scan_file(REGA0 struct Hook *hook,REGA2 struct GlobalData *gd,REGA1 struct spMsg *msg)
  581. {
  582.    STRPTR path  = msg->Path;
  583.    STRPTR gpath = msg->RealPath;
  584.    ULONG filetype;
  585.  
  586.    DB(("msg  : %ld\n",msg->Msg));
  587.    DB(("path : %s\n",msg->Path));
  588.  
  589.    switch(msg->Msg)
  590.    {
  591.    case SPM_DIR:
  592.  
  593.       gd->gd_SStat.ss_ActDirectories++;
  594.  
  595.       if(gd->gd_Workbench)
  596.       {
  597.          sprintf(gd->gd_TempBuffer,"(%3ld/%3ld)",gd->gd_SStat.ss_ActDirectories,gd->gd_SStat.ss_Directories);
  598.          draw_scanwindowtext(&gd->gd_SWin,NUM_DIRS,gd->gd_TempBuffer);
  599.  
  600.          draw_scanwindowtext(&gd->gd_SWin,NUM_DIR,gpath);
  601.       } else if(gd->gd_Para[ARG_VERBOSE])
  602.          Printf ("\rScanning dir (%3ld/%3ld) : %-40s\n",
  603.                   gd->gd_SStat.ss_ActDirectories,
  604.                   gd->gd_SStat.ss_Directories,
  605.                   msg->RealPath);
  606.  
  607.       break;
  608.    case SPM_FILE:
  609.       gd->gd_SStat.ss_ActFiles++;
  610.  
  611.       if(gd->gd_Workbench)
  612.       {
  613.          sprintf(gd->gd_TempBuffer,"(%3ld/%3ld)",gd->gd_SStat.ss_ActFiles,gd->gd_SStat.ss_Files);
  614.  
  615.          draw_scanwindowtext(&gd->gd_SWin,NUM_FILES    ,gd->gd_TempBuffer);
  616.          draw_scanwindowtext(&gd->gd_SWin,NUM_FILE     ,FilePart(path));
  617.       } else if(gd->gd_Para[ARG_VERBOSE])
  618.          Printf ("\rScanning file (%3ld/%3ld) : %s",
  619.                  gd->gd_SStat.ss_ActFiles,
  620.                  gd->gd_SStat.ss_Files,
  621.                  path);
  622.  
  623.       DB(("scanfile : %s\n",path));
  624.  
  625.       if((filetype = getfiletype(msg->FHandle,msg->RealPath)) != FTYPE_UNKNOWN)
  626.       {
  627.          gd->gd_ReadFH = msg->FHandle;
  628.  
  629.          if(gd->gd_Workbench)
  630.             draw_scanwindowtext(&gd->gd_SWin,NUM_FILETYPE ,ftype[filetype]);
  631.          else if(gd->gd_Para[ARG_VERBOSE])
  632.             Printf (" (%s)%-30s\n",ftype[filetype],"");
  633.  
  634.          gd->gd_FileName = path;
  635.          gd->gd_FileType = filetype;
  636.          
  637.          gd->gd_FileSize = msg->Fib->fib_Size;
  638.  
  639.          /* manipulate the filepart of the msg->Path (this is save for scan_patterns()) */
  640.          convertsuffix(filetype,path);
  641.  
  642.          DB(("after convertsuffix : %s %s !\n",path,ftype[filetype]));
  643.  
  644.          if(gd->gd_Workbench)
  645.             draw_gauge(&gd->gd_SWin.sw_Actual,0,0);
  646.  
  647.          switch(filetype)
  648.          {
  649.          case FTYPE_HEADER:
  650.             scan_header(gd);
  651.             break;
  652.          case FTYPE_AUTODOC:
  653.          case FTYPE_DOC:
  654.             scan_autodoc(gd);
  655.             break;
  656.          case FTYPE_AMIGAGUIDE:
  657.             scan_amigaguide(gd);
  658.             break;
  659.          case FTYPE_MAN:
  660.             scan_man(gd);
  661.             break;
  662.          }
  663.  
  664.          DB(("before scan_file Close(readfh)\n"));
  665.       
  666.          gd->gd_ReadFH = NULL;
  667.       } else
  668.       {  
  669.          if(gd->gd_Workbench)
  670.             draw_scanwindowtext(&gd->gd_SWin,NUM_FILETYPE ,"unknown");
  671.          else if(gd->gd_Para[ARG_VERBOSE])
  672.             Printf ("(unknown)%-30s\n","");
  673.       }
  674.       DB(("scan_file : end !\n"));
  675.  
  676.       gd->gd_SStat.ss_ActTotalFileSize += msg->Fib->fib_Size;
  677.  
  678.       if(!gd->gd_Abort)
  679.          draw_state(gd);
  680.  
  681.       break;
  682.    }
  683.  
  684.    if(check_abort(gd))
  685.       return(ERROR_BREAK);
  686.  
  687.    return(0);
  688. }
  689. /*FE*/
  690.  
  691. /* -------------------------- scan specific file -------------------------- */
  692.  
  693. /*FS*//*"void scan_header(struct GlobalData *gd)"*/
  694. void scan_header(struct GlobalData *gd)
  695. {
  696.    STRPTR ptr;
  697.    STRPTR name;
  698.    ULONG add;
  699.    ULONG type;
  700.    ULONG line = 0;
  701.  
  702.    WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     ,XREFT_INCLUDE,
  703.                                       ENTRYA_Name     ,gd->gd_FileName,
  704.                                       ENTRYA_File     ,gd->gd_FileName,
  705.                                       ENTRYA_NodeName ,mainstring,
  706.                                       TAG_DONE);
  707.  
  708.    draw_info(gd,gd->gd_FileName,XREFT_INCLUDE);
  709.  
  710.    while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)) && !check_abort(gd))
  711.    {
  712.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  713.          draw_state(gd);
  714.  
  715.       line++;
  716.  
  717.       while(*ptr == ' ' || *ptr == '\t')
  718.          ptr++;
  719.  
  720.       if(!strncmp(ptr,"struct",6))
  721.       {
  722.          ptr += 6;
  723.  
  724.          name = ptr;
  725.  
  726.          while(*ptr == ' ' || *ptr == '\t')
  727.             ptr++;
  728.  
  729.          if(name != ptr)
  730.          {
  731.             name = ptr;
  732.  
  733.             while(*ptr != '{' && *ptr != ' ' && *ptr != '\t' && *ptr != '\n')
  734.                ptr++;
  735.  
  736.             *ptr++ = EOS;
  737.  
  738.             while(*ptr == ' ' || *ptr == '\t' && *ptr == '\n')
  739.                ptr++;
  740.  
  741.             add = 0;
  742.  
  743.             if(*ptr == EOS)
  744.             {
  745.                while(ptr && (ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)))
  746.                {
  747.                   add++;
  748.  
  749.                   if(*ptr != '\n')
  750.                      break;
  751.                }
  752.  
  753.                if(!ptr)
  754.                   break;
  755.             }
  756.  
  757.             if(*ptr == '{')
  758.             {
  759.  
  760.                if(WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     ,XREFT_STRUCT,
  761.                                                      ENTRYA_Name     ,name,
  762.                                                      ENTRYA_File     ,gd->gd_FileName,
  763.                                                      ENTRYA_Line     ,line,
  764.                                                      ENTRYA_NodeName ,mainstring,
  765.                                                      TAG_DONE))
  766.                {
  767.                   draw_info(gd,name,XREFT_STRUCT);
  768.                }
  769.             }         
  770.             gd->gd_Line += add;
  771.             line += add;
  772.          }
  773.       } else if(!strncmp(ptr,"#define",7))
  774.       {
  775.          ptr += 7;
  776.  
  777.          while(*ptr == ' ' || *ptr == '\t')
  778.             ptr++;
  779.  
  780.          name = ptr;
  781.  
  782.          while(*ptr != ' ' && *ptr != '\t' && *ptr != '(' && *ptr != '\n')   
  783.             ptr++;
  784.  
  785.          if(*ptr == '(')
  786.             type = XREFT_MACRO;
  787.          else
  788.             type = XREFT_DEFINE;
  789.  
  790.          *ptr = EOS;
  791.  
  792.          if(WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     ,type,
  793.                                                ENTRYA_Name     ,name,
  794.                                                ENTRYA_File     ,gd->gd_FileName,
  795.                                                ENTRYA_Line     ,line,
  796.                                                ENTRYA_NodeName ,mainstring,
  797.                                                TAG_DONE))
  798.          {
  799.             draw_info(gd,name,type);
  800.          }
  801.       } else if(!strncmp(ptr,"typedef",7))
  802.       {
  803.          ptr += 7;
  804.  
  805.          while(*ptr != ';' && *ptr != EOS)
  806.          {
  807.             while(*ptr == ' ' || *ptr == '\t' || *ptr == '*')
  808.                ptr++;
  809.  
  810.             if(*ptr != ';')
  811.                name = ptr;
  812.  
  813.             while(*ptr != ';' && *ptr != EOS && *ptr != ' ' && *ptr != '\t')
  814.                ptr++;
  815.          }
  816.  
  817.          if(*ptr == ';')
  818.          {
  819.             *ptr = EOS;
  820.             if(WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     , XREFT_TYPEDEF,
  821.                                                   ENTRYA_Name     , name,
  822.                                                   ENTRYA_Line     , line,
  823.                                                   ENTRYA_File     , gd->gd_FileName,
  824.                                                   ENTRYA_NodeName , mainstring,
  825.                                                   TAG_DONE))
  826.             {
  827.                draw_info(gd,name,XREFT_TYPEDEF);
  828.             }
  829.          }
  830.       }
  831.    }
  832. }
  833. /*FE*/
  834. /*FS*//*"void scan_autodoc(struct GlobalData *gd)"*/
  835. void scan_autodoc(struct GlobalData *gd)
  836. {
  837.    STRPTR ptr;
  838.    STRPTR name;
  839.    ULONG type;
  840.    BOOL autodoc = TRUE;
  841.    BOOL formfeed = FALSE;
  842.  
  843.    DB(("path : %s\n",gd->gd_FileName));
  844.  
  845.    while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)) && !check_abort(gd))
  846.    {
  847.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  848.          draw_state(gd);
  849.  
  850.       while(*ptr == ' ' || *ptr == '\t')
  851.          ptr++;
  852.  
  853.       if(*ptr == '\f')
  854.       {
  855.          formfeed = TRUE;
  856.          ptr++;
  857.       }
  858.  
  859.       /* continue on an empty line */
  860.       if(*ptr == '\n')
  861.          continue;
  862.  
  863.       if(formfeed)
  864.       {
  865.          STRPTR ptr2 = ptr;
  866.  
  867.          while(*ptr2 != ' ' && *ptr2 != '\t' && *ptr2 != '\n' && *ptr2 != EOS)
  868.             ptr2++;
  869.  
  870.          *ptr2 = EOS;
  871.  
  872.          if(strlen(ptr) > 40)
  873.             ptr += (strlen(ptr) >> 1);
  874.  
  875.          strcpy(gd->gd_TempBuffer,FilePart(ptr));
  876.  
  877.          if(checkentrytype(gd->gd_TempBuffer) == XREFT_FUNCTION &&
  878.             strcmp(&gd->gd_TempBuffer[strlen(gd->gd_TempBuffer) - 2],"()"))
  879.             strcat(gd->gd_TempBuffer,"()");
  880.  
  881.          formfeed = FALSE;
  882.       }
  883.  
  884.       if(!strncmp(ptr,"NAME",4))
  885.       {
  886.          ptr += 4;
  887.          while(*ptr == ' ' || *ptr == '\t')
  888.             ptr++;
  889.  
  890.          if(*ptr == '\n')
  891.             while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)))
  892.             {
  893.                while(*ptr == ' ' || *ptr == '\t')
  894.                   ptr++;
  895.  
  896.                /* break on an empty line */
  897.                if(*ptr == '\n')
  898.                   break;
  899.  
  900.                name = ptr;
  901.  
  902.                while(*ptr != ' ' && *ptr != '\t' && *ptr != '-' && *ptr != '\n')
  903.                   ptr++;
  904.  
  905.                if(gd->gd_FileType == FTYPE_AUTODOC)
  906.                {
  907.                   STRPTR ptr2 = ptr;
  908.  
  909.                   autodoc = TRUE;
  910.  
  911.                   while(*ptr2 == ' ' || *ptr2 == '\t')
  912.                      ptr2++;
  913.  
  914.                   if(*ptr2 != '-')
  915.                      autodoc = FALSE;
  916.                }
  917.  
  918.                *ptr = EOS;
  919.  
  920.                if(autodoc)
  921.                {
  922.                   name = FilePart(name);
  923.  
  924.                   if(gd->gd_FileType == FTYPE_AUTODOC)
  925.                   {
  926.                      type = checkentrytype(name);
  927.  
  928.                      if(type == XREFT_FUNCTION && strcmp(&name[strlen(name) - 2],"()"))
  929.                         strcat(name,"()");
  930.                   }
  931.  
  932.                   DB(("name     : %s\n",name));
  933.                   DB(("nodename : %s\n",gd->gd_TempBuffer));
  934.  
  935.                   if(WriteXRefFileEntry(gd->gd_XRefFile,
  936.                                         ENTRYA_Type      , type,
  937.                                         ENTRYA_Name      , name,
  938.                                         ENTRYA_File      , gd->gd_FileName,
  939.                                         ENTRYA_NodeName  , gd->gd_TempBuffer,
  940.                                         ENTRYA_CheckMode , ENTRYCHECK_FILE,
  941.                                         TAG_DONE))
  942.                   {
  943.                      draw_info(gd,name,type);
  944.                   }
  945.                }
  946.             }
  947.       } else if(!strcmp(ptr,"TABLE OF CONTENTS\n"))
  948.       {
  949.          while(ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN))
  950.          {
  951.  
  952.             draw_state(gd);
  953.  
  954.             while(*ptr == ' ' || *ptr == '\t')
  955.                ptr++;
  956.  
  957.             if(*ptr == '\f')
  958.                break;
  959.  
  960.             if(*ptr == '\n')
  961.                continue;
  962.  
  963.             name = ptr;
  964.  
  965.             while(*ptr != EOS && *ptr != '\n')
  966.                ptr++;
  967.  
  968.             *ptr = EOS;
  969.  
  970.             name = FilePart(name);
  971.  
  972.             type = checkentrytype(name);
  973.  
  974.             if(type == XREFT_FUNCTION && strcmp(&name[strlen(name) - 2],"()"))
  975.                strcat(name,"()");
  976.  
  977.             if(WriteXRefFileEntry(gd->gd_XRefFile,
  978.                                   ENTRYA_Type      ,type,
  979.                                   ENTRYA_Name      ,name,
  980.                                   ENTRYA_File      ,gd->gd_FileName,
  981.                                   ENTRYA_NodeName  ,name,
  982.                                   ENTRYA_CheckMode ,ENTRYCHECK_FILE,
  983.                                   TAG_DONE))
  984.             {
  985.                draw_info(gd,name,type);
  986.             }
  987.          }
  988.       }
  989.    }
  990. }
  991. /*FE*/
  992. /*FS*//*"void scan_amigaguide(struct GlobalData *gd)"*/
  993. void scan_amigaguide(struct GlobalData *gd)
  994. {
  995.    STRPTR ptr;
  996.    STRPTR name;
  997.    ULONG type;
  998.  
  999.    while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)) && !check_abort(gd))
  1000.    {
  1001.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1002.          draw_state(gd);
  1003.  
  1004.       if(!Strnicmp(ptr,"@node",5))
  1005.       {
  1006.          ptr += 5;
  1007.  
  1008.          while(*ptr == ' ' || *ptr == '\t')
  1009.             ptr++;
  1010.  
  1011.          if(*ptr == '"')
  1012.             ptr++;
  1013.  
  1014.          name = ptr;
  1015.  
  1016.          while(*ptr != '"' && *ptr != ' ' && *ptr != '\t' && *ptr != '\n' && *ptr != ' ')
  1017.             ptr++;
  1018.  
  1019.          *ptr = EOS;
  1020.  
  1021.          type = checkentrytype(name);
  1022.  
  1023.          if(WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     ,type,
  1024.                                                ENTRYA_File     ,gd->gd_FileName,
  1025.                                                ENTRYA_Name     ,name,
  1026.                                                ENTRYA_NodeName ,name,
  1027.                                                TAG_DONE))
  1028.          {
  1029.             draw_info(gd,name,type);
  1030.          }
  1031.       }
  1032.    }
  1033. }
  1034. /*FE*/
  1035. /*FS*/ /*"void scan_man(struct GlobalData *gd) "*/
  1036. void scan_man(struct GlobalData *gd)
  1037. {
  1038.    STRPTR ptr;
  1039.    STRPTR name;
  1040.    ULONG type;
  1041.    BOOL go = TRUE;
  1042.    BOOL eos;
  1043.  
  1044.    DB(("path : %s\n",gd->gd_FileName));
  1045.  
  1046.    while(go && (ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)) && !check_abort(gd))
  1047.    {
  1048.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1049.          draw_state(gd);
  1050.  
  1051.       while(*ptr == ' ' || *ptr == '\t')
  1052.          ptr++;
  1053.  
  1054.       if(!strcmp(ptr,"N\010NA\010AM\010ME\010E\n"))
  1055.       {
  1056.          while(*ptr != '-' && *ptr != EOS && (ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,BUFFER_LEN)))
  1057.          {
  1058.             while(*ptr != '-' && *ptr != EOS)
  1059.             {
  1060.                while(*ptr == ' ' || *ptr == '\t')
  1061.                   ptr++;
  1062.  
  1063.                name = gd->gd_TempBuffer;
  1064.  
  1065.                while(*ptr != ' ' && *ptr != '\t' && *ptr != '-' &&
  1066.                      *ptr != ',' && *ptr != '\n' && *ptr != EOS)
  1067.                {
  1068.                   if(ptr[1] == '\010')
  1069.                   {
  1070.                      ptr += 2;
  1071.                      *name++ = *ptr;
  1072.                   } else
  1073.                      *name++ = *ptr;
  1074.                   ptr++;
  1075.                }
  1076.  
  1077.                *name = EOS;
  1078.                name = gd->gd_TempBuffer;
  1079.  
  1080.                if(*ptr != '-')
  1081.                {
  1082.                   eos = FALSE;
  1083.  
  1084.                   if(*ptr == EOS)
  1085.                      eos = TRUE;
  1086.                   else
  1087.                      *ptr = EOS;
  1088.  
  1089.                   type = checkentrytype(name);
  1090.  
  1091.                   if(WriteXRefFileEntry(gd->gd_XRefFile,ENTRYA_Type     , type,
  1092.                                                         ENTRYA_Name     , name,
  1093.                                                         ENTRYA_File     , gd->gd_FileName,
  1094.                                                         ENTRYA_NodeName , mainstring,
  1095.                                                         TAG_DONE))
  1096.                   {
  1097.                      draw_info(gd,name,type);
  1098.                   }
  1099.  
  1100.                   if(!eos)
  1101.                      ptr++;
  1102.                }
  1103.             }
  1104.          }
  1105.          go = FALSE;
  1106.       }
  1107.    }
  1108. }
  1109. /*FE*/
  1110.  
  1111. /* ---------------------------- abort function ---------------------------- */
  1112.  
  1113. /*FS*/ /*"BOOL check_abort(struct GlobalData *gd)"*/
  1114. BOOL check_abort(struct GlobalData *gd)
  1115. {
  1116.    if(gd->gd_SWin.sw_Window)
  1117.    {
  1118.       struct IntuiMessage *msg;
  1119.  
  1120.       while((msg = (struct IntuiMessage *) GetMsg(gd->gd_SWin.sw_Window->UserPort)))
  1121.       {
  1122.          switch(msg->Class)
  1123.          {
  1124.          case IDCMP_CLOSEWINDOW:
  1125.             gd->gd_Abort = TRUE;
  1126.             break;
  1127.          case IDCMP_VANILLAKEY:
  1128.             /* check if ctrl-c or ecs was pressed ? */
  1129.             if(msg->Code == 3 || msg->Code == 27)
  1130.                gd->gd_Abort = TRUE;
  1131.             break;
  1132.          }
  1133.          ReplyMsg((struct Message *) msg);
  1134.       }
  1135.  
  1136.       if(gd->gd_Abort)
  1137.          draw_scanwindowstatus(&gd->gd_SWin,"aborted !");
  1138.    }
  1139.  
  1140.    gd->gd_Abort |= (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C);
  1141.  
  1142.    return(gd->gd_Abort);
  1143. }
  1144. /*FE*/
  1145.  
  1146. /* --------------------------- displays function --------------------------- */
  1147.  
  1148. /*FS*/ /*"void draw_info(struct GlobalData *gd,STRPTR entry,ULONG entrytype)"*/
  1149. void draw_info(struct GlobalData *gd,STRPTR entry,ULONG entrytype)
  1150. {
  1151.    gd->gd_Entries++;
  1152.  
  1153.    if(gd->gd_Workbench)
  1154.    {
  1155.       UBYTE buf[100];
  1156.  
  1157.       sprintf(buf,"%s (%s)",entry,etype[entrytype]);
  1158.       draw_scanwindowtext(&gd->gd_SWin,NUM_ENTRY,buf);
  1159.       sprintf(buf,"%ld",gd->gd_Entries);
  1160.       draw_scanwindowtext(&gd->gd_SWin,NUM_ENTRIES,buf);
  1161.    }
  1162. }
  1163. /*FE*/
  1164. /*FS*/ /*"void draw_state(struct GlobalData *gd)"*/
  1165. void draw_state(struct GlobalData *gd)
  1166. {
  1167.    if(gd->gd_Workbench || gd->gd_Para[ARG_VERBOSE])
  1168.    {
  1169.       ULONG current;
  1170.       ULONG acttotal;
  1171.  
  1172.       if(gd->gd_ReadFH)
  1173.       {
  1174.          current = Seek(gd->gd_ReadFH,0,OFFSET_CURRENT);
  1175.          acttotal = gd->gd_SStat.ss_ActTotalFileSize + current;
  1176.       } else
  1177.       {
  1178.          current = gd->gd_FileSize;
  1179.          acttotal = gd->gd_SStat.ss_ActTotalFileSize;
  1180.       }
  1181.  
  1182.       time_calc(&gd->gd_TimeCalc,acttotal,
  1183.                                  gd->gd_SStat.ss_TotalFileSize);
  1184.  
  1185.       if(gd->gd_Workbench)
  1186.       {
  1187.          draw_gauge(&gd->gd_SWin.sw_Actual,current,gd->gd_FileSize);
  1188.          draw_gauge(&gd->gd_SWin.sw_Total ,acttotal,
  1189.                                            gd->gd_SStat.ss_TotalFileSize);
  1190.  
  1191.          draw_scanwindowtime(&gd->gd_SWin,gd->gd_TimeCalc.tc_Secs);
  1192.       }
  1193.       {
  1194.          Printf ("\rScanning (%6ld/%6ld) , Time Exp. : %02ld:%02ld , Left : %02ld:%02ld",
  1195.                  current,gd->gd_FileSize,
  1196.                  gd->gd_TimeCalc.tc_Secs[TIME_EXPECTED] / 60,gd->gd_TimeCalc.tc_Secs[TIME_EXPECTED] % 60,
  1197.                  gd->gd_TimeCalc.tc_Secs[TIME_LEFT]     / 60,gd->gd_TimeCalc.tc_Secs[TIME_LEFT]     % 60);
  1198.       }
  1199.    }
  1200. }
  1201. /*FE*/
  1202.  
  1203.